from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

def get_local_time():
    """获取本地时间"""
    return datetime.now()

# 测试用例模型
class TestCase:
    def __init__(self):
        pass
    
    @staticmethod
    def define(db, suite_case_association, precondition_association):
        class TestCaseModel(db.Model):
            __tablename__ = 'test_cases'
            id = db.Column(db.Integer, primary_key=True)
            name = db.Column(db.String(100), nullable=False)
            description = db.Column(db.Text)
            url = db.Column(db.String(200))
            steps = db.Column(db.Text)  # JSON格式存储测试步骤
            priority = db.Column(db.String(2), default='P3', nullable=False)  # 优先级字段：P1、P2、P3、P4
            created_at = db.Column(db.DateTime, default=get_local_time)
            updated_at = db.Column(db.DateTime, default=get_local_time, onupdate=get_local_time)
            is_deleted = db.Column(db.Boolean, default=False)  # 逻辑删除标识
            
            # 关联的测试套件（反向引用）
            test_suites = db.relationship('TestSuiteModel', secondary=suite_case_association, back_populates='test_cases')
            
            # 前置条件关联（自引用多对多关系）
            precondition_test_cases = db.relationship(
                'TestCaseModel',
                secondary=precondition_association,
                primaryjoin='TestCaseModel.id == precondition_association.c.test_case_id',
                secondaryjoin='TestCaseModel.id == precondition_association.c.precondition_test_case_id',
                backref='dependent_test_cases'
            )
            
            def to_dict(self):
                return {
                    'id': self.id,
                    'name': self.name,
                    'description': self.description,
                    'url': self.url,
                    'steps': self.steps,
                    'priority': self.priority,
                    'created_at': self.created_at.isoformat() if self.created_at else None,
                    'updated_at': self.updated_at.isoformat() if self.updated_at else None,
                    'is_deleted': self.is_deleted,
                    'precondition_test_case_ids': [precondition.id for precondition in self.precondition_test_cases],
                    'precondition_test_cases': [precondition.to_dict() for precondition in self.precondition_test_cases],
                    # 计算被引用次数
                    'referenced_count': len(self.dependent_test_cases),
                    # 判断是否有前置条件
                    'has_preconditions': len(self.precondition_test_cases) > 0,
                    # 添加has_dependency字段以匹配前端需求
                    'has_dependency': len(self.precondition_test_cases) > 0,
                    # 添加关联的测试套件信息
                    'test_suites': [suite.to_dict() for suite in self.test_suites]
                }
            
            def __repr__(self):
                return f'<TestCase {self.name}>'
        
        return TestCaseModel

# 测试套件模型
class TestSuite:
    def __init__(self):
        pass
    
    @staticmethod
    def define(db, suite_case_association):
        class TestSuiteModel(db.Model):
            __tablename__ = 'test_suites'
            id = db.Column(db.Integer, primary_key=True)
            name = db.Column(db.String(100), nullable=False)
            description = db.Column(db.Text)
            browser = db.Column(db.String(20), default='edge')  # edge, chrome, firefox
            created_at = db.Column(db.DateTime, default=get_local_time)
            updated_at = db.Column(db.DateTime, default=get_local_time, onupdate=get_local_time)
            is_deleted = db.Column(db.Boolean, default=False)  # 逻辑删除标识
            
            # 关联的测试用例（反向引用）
            test_cases = db.relationship('TestCaseModel', secondary=suite_case_association, back_populates='test_suites')
            
            def to_dict(self):
                return {
                    'id': self.id,
                    'name': self.name,
                    'description': self.description,
                    'browser': self.browser,
                    'created_at': self.created_at.isoformat() if self.created_at else None,
                    'updated_at': self.updated_at.isoformat() if self.updated_at else None,
                    'is_deleted': self.is_deleted,
                    'test_case_ids': [test_case.id for test_case in self.test_cases]
                }
            
            def __repr__(self):
                return f'<TestSuite {self.name}>'
        
        return TestSuiteModel

# 测试结果模型
class TestResult:
    def __init__(self):
        pass
    
    @staticmethod
    def define(db):
        class TestResultModel(db.Model):
            __tablename__ = 'test_results'
            id = db.Column(db.Integer, primary_key=True)
            test_case_id = db.Column(db.Integer, db.ForeignKey('test_cases.id'))
            status = db.Column(db.String(20))  # PASS, FAIL, ERROR
            execution_time = db.Column(db.Float)  # 执行时间（秒）
            log = db.Column(db.Text)  # 执行日志
            screenshot_path = db.Column(db.String(200))  # 截图路径
            executed_at = db.Column(db.DateTime, default=get_local_time)
            
            # 关联测试用例
            test_case = db.relationship('TestCaseModel', backref='results')
            
            def to_dict(self):
                return {
                    'id': self.id,
                    'test_case_id': self.test_case_id,
                    'status': self.status,
                    'execution_time': self.execution_time,
                    'log': self.log,
                    'screenshot_path': self.screenshot_path,
                    'executed_at': self.executed_at.isoformat() if self.executed_at else None,
                    'test_case': self.test_case.to_dict() if self.test_case else None
                }
            
            def __repr__(self):
                return f'<TestResult {self.status}>'
        
        return TestResultModel

# 定义模型工厂函数
def define_models(db):
    # 测试套件和测试用例关联表
    suite_case_association = db.Table('suite_case_association',
        db.Column('suite_id', db.Integer, db.ForeignKey('test_suites.id'), primary_key=True),
        db.Column('test_case_id', db.Integer, db.ForeignKey('test_cases.id'), primary_key=True)
    )
    
    # 前置条件关联表（测试用例自引用）
    precondition_association = db.Table('precondition_association',
        db.Column('test_case_id', db.Integer, db.ForeignKey('test_cases.id'), primary_key=True),
        db.Column('precondition_test_case_id', db.Integer, db.ForeignKey('test_cases.id'), primary_key=True)
    )
    
    TestCaseModel = TestCase().define(db, suite_case_association, precondition_association)
    TestSuiteModel = TestSuite().define(db, suite_case_association)
    TestResultModel = TestResult().define(db)
    
    return TestCaseModel, TestSuiteModel, TestResultModel